#include "thread_pool.h"
#include <mysql/mysql.h>
#include <string.h>

extern const char* rootfile;
extern MYSQL* conn;


//文件上传的操作
int putsFile(int sockfd, char *path, int length);    

void putsCommand(task_t* task){
    printf("execute putsCommand,\n");

    char filename[128] = {0};
    int userid = 0;
    char md5_hash[33] = {0};
    int length = 0;

    strcpy(filename, task->data);

    recvn(task->peerfd, &userid, sizeof(userid));

    recvn(task->peerfd, md5_hash, 32);

    int err = recvn(task->peerfd, &length, sizeof(length));
    if(err == -1){
        perror("recvFile: recv filename length is error");
        return ;
    }
    printf("filename: %s\n", filename);
    printf("userid: %d\n", userid);
    printf("md5: %s\n", md5_hash);
    printf("file length:%d\n", length);

    //根据fd获得用户id
    getUserid(task->peerfd, &userid);

    //数据库搜索拿到当前路径
    int pwdid = -1;
    char query[256] = {0};
    sprintf(query, 
            "SELECT pwdid FROM t_user WHERE userid=%d", userid);
    mysql_query(conn, query);
    MYSQL_RES* res = mysql_store_result(conn);
    MYSQL_ROW row = mysql_fetch_row(res);
    pwdid = atoi(row[0]);
    printf("pwdid: %d\n", pwdid);

    //检查是否可以文件秒传
    memset(query, 0, sizeof(query));
    sprintf(query, 
            "SELECT fid FROM t_file WHERE md5='%s'", md5_hash);
    mysql_query(conn, query);
    res = mysql_store_result(conn);
    int cnt_md5 = mysql_num_rows(res);
    printf("md5_count: %d\n", cnt_md5);

    //告知对端是否可以文件秒传
    if(cnt_md5 == 0){
        sendMsg(task->peerfd, MSG_TYPE_TRANSFER_NORMAL, "\0");
    } else {
        sendMsg(task->peerfd, MSG_TYPE_TRANSFER_SECOND, "\0");
    }

    if(cnt_md5 == 0){   //只能正常上传
        //路径拼接
        char path[64] = {0};
        sprintf(path, "%s%s", rootfile, md5_hash);

        if(putsFile(task->peerfd, path, length)){
            sendMsg(task->peerfd, MSG_TYPE_FAILURE, "Failed to upload.");
            syslog(LOG_ERR, "User execute PUTSFILE command: FAILED.");
            return ;
        };    
    };


    //虚拟文件表中增加表项
    memset(query, 0, sizeof(query));
    sprintf(query,
            "INSERT INTO t_file(parent_id,filename,owner_id,md5,filesize,type) "
             "VALUES(%d,'%s',%d,'%s',%d,'f')"
            , pwdid, filename, userid, md5_hash, length);
    int ret =  mysql_query(conn, query);
    if(ret){
        fprintf(stderr, "%s\n", mysql_error(conn));
    }

    int affect_row = mysql_affected_rows(conn);
    if(affect_row == 1){    //添加成功
        sendMsg(task->peerfd, MSG_TYPE_SUCCESS, "Upload successfully.");
        syslog(LOG_INFO, "User %d puts file %s successfully.", userid, filename);
    } else {    //添加失败
        sendMsg(task->peerfd, MSG_TYPE_ERROR_MYSQL, 
                "An error occurred while we were adding data to the data table.");
    }

}



int putsFile(int sockfd, char *path, int length){

    //接收文件内容
    int filefd = open(path, O_RDWR|O_CREAT|O_TRUNC, 0640);
    if(filefd<0){
        perror("recvFile: open file is failed");
        return 1;
    }

    int donesize = 0;
    if(length>100*1024*1024){
        ftruncate(filefd, length);
        void*p = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, filefd, 0);
        if(p==NULL){
            close(filefd);
            fprintf(stderr, "mmap is failed\n");
            return 1;
        }
        int ret = recvn(sockfd, (char*)p, length);
        if(ret == -1){
            close(filefd);
            perror("recvFile: recv file data is failed");
            return 1;
        }
        donesize += ret;
        munmap(p, length);

    }else{
        char buff[1000];
        while(donesize<length){
            int len = 0;
            int ret = recvn(sockfd, &len, sizeof(len));
            if(ret<=0){
                perror("recv file len is failed");
                close(filefd);
                return 1;
            }
            ret = recvn(sockfd, buff, len);
            if(ret<=0){
                perror("recv file data is failed");
                close(filefd);
                return 1;
            }
            int err = write(filefd, buff, ret);
            if(err == -1){
                perror("recvFile: write file data is failed");
                close(filefd);
                return 1;
            }
            donesize += ret;
            printf("The file is recv: %5.2f%%\r", 100.00*donesize/length);
            fflush(stdout);
        }
        printf("\n");
    }
    close(filefd);

    if(donesize == length){
        printf("recv file successfully.\n");
        return 0;
    }
    printf("failed to recv file.\n");
    return 1;
}
